﻿package org.cshoo.sys.util;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.cshoo.sys.data.entity.Authority;
import org.cshoo.sys.data.entity.Menu;

/**
 * 此类用于构造菜单树，用到两个递归方法，对树进行权限分析做修剪工作
 * @author 杨翼
 * 2013年5月15日
 */
public class FilterMenuTree {
	
	/**
	 * 对菜单list menuList 进行权限过滤
	 * @param menuList 菜单list
	 * @param authorityList 权限list
	 */
	public static List filterMenuList(List<Menu> menuList,List<Authority> authorityList)
	{
		List result = new ArrayList();
		//构造root节点，将menuList中的menu全挂在上面，以便调用下面的递归方法对其进行修剪
		Menu root = new Menu();
		Set<Menu> children = new HashSet<Menu>();
		for(Menu menu : menuList)
		{
			children.add(menu);
		}
		//root.setChildren(children);
		pruneMenu(root,authorityList);
		
		for(Menu menu : root.getChildren())
		{
			result.add(menu);
		}
		return result;
	}
	
	/**
	 * 此方法用递归的方法，对菜单树进行剪修，剪掉其中的无效节点；
	 * @param menu
	 * @param authorityList
	 */
	private static void pruneMenu(Menu menu,List<Authority> authorityList)
	{   
		//如果此节点不是叶子节点对它进行裁剪
		if(!menu.getChildren().isEmpty())
		{
			for(Menu child : menu.getChildren())
			{
				//如果它的子节点不是有效的，那么将它剪掉
				if(!isEffectiveNode(child,authorityList))
				{
					menu.getChildren().remove(child);
				}
				//如果它是子节点是有效的，并且它不是叶子节点，对它的子节点也做修剪工作，此处产生自身递归
				else if(!child.getChildren().isEmpty())
				{
					pruneMenu(child,authorityList);
				}
			}
		}
		
	}
	
	
	/**
	 * 判断此节点是否为有效节点，如果此节点为叶子节点，并且在授权列表中包含，那么它为有效节点
	 * 如果此节点不为叶子节点，并且它的子节点均为无效节点，那么它也为无效节点
	 * @param menu
	 * @param authorityList
	 * @return
	 */
	private static Boolean isEffectiveNode(Menu menu,List<Authority> authorityList)
	{
		//如果是叶子节点，判断是否为有效
		if(menu.getChildren().isEmpty())
		{
			if(isInAuthorityList(menu,authorityList))
				return true;
		}
		//如果是非叶子节点，用递归的方法判断它是否为有效节点，即看它的子节点是否为有效节点，此处产生自身递归
		else
		{
			for(Menu child:menu.getChildren())
			{
				return isEffectiveNode(child,authorityList);
			}
		}
		return false;
	}
	
	
	/**
	 * 判断叶子节点是否在授权列表中
	 * @param menu
	 * @param authorityList
	 * @return
	 */
	private static Boolean isInAuthorityList(Menu menu,List<Authority> authorityList)
	{
		for(Authority authority : authorityList)
		{
			if(authority.getMenu().getId().equals(menu.getId()))
				return true;
		}
		return false;
	}
	
}
